/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package core;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import model.Costumer;
import model.Dapcomposition;
import model.DapcompositionId;
import model.Dapstructure;
import model.Dapversion;
import model.Decision;
import model.Department;
import model.Docversion;
import model.Employee;
import model.Processowner;
import model.Stepvalidation;
import static oracle.jrockit.jfr.events.Bits.intValue;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import util.ProjetHibernateUtil;

/**
 *
 * @author phinguyen
 */
public class ProcessOwnerCore {

    private static Session session;

    ArrayList<Dapstructure> lstDapStructure;
    ArrayList<Stepvalidation> lstStepvalidation;

    /**
     * constructor obtention de la session qui synchronisra les objets
     */
    public ProcessOwnerCore() {

        this.session = ProjetHibernateUtil.getSessionFactory().openSession();
        Query queryDapS = session.getNamedQuery("HQL_ALL_DAPSTRUCTURE");
        lstDapStructure = new ArrayList();
        lstDapStructure.addAll(queryDapS.list());

    }
/**
 * return all Steps from Database
 * @return 
 */
    public List getAllSteps() {
        return this.session.getNamedQuery("lstStepValidation").list();
    }
/**
 * return all Departements from Database
 * @return 
 */
    public List<Department> getAllDepartment() {
        return this.session.getNamedQuery("HQL_ALL_DEPARTMENT").list();
    }
/**
 * insert into database a structure of DAP
 * @param dap 
 */
    public void saveDAP(Dapstructure dap) {
        this.session.beginTransaction();
        this.session.save(dap);
        this.session.getTransaction().commit();
    }
/**
 * insert into database a Proces Owner
 * @param po
 */
    public void saveProcessOwner(Processowner po) {
        this.session.beginTransaction();
        this.session.save(po);
        this.session.getTransaction().commit();
    }
/**
 * insert into database a step linked to a Department
 * @param sname 
 * @param department
 * @return 
 */
    public Stepvalidation saveStep(String sname, Department department) {
        Stepvalidation newstep = new Stepvalidation(sname, department);
        Transaction tr = session.getTransaction();
        tr.begin();
        session.saveOrUpdate(newstep);
        tr.commit();
        return newstep;
    }
    /**
     * get all Process owner from Database
     * @return 
     */

    public List<Processowner> getlstPO() {

        return session.getNamedQuery("HQL_ALL_PROCESSOWNER").list();

    }
/**
 * get a process owner from database by mail
 * @param mail
 * @return 
 */
    public Processowner getPO(String mail) {

        boolean trouve = false;
        int i = 0;
        int position = 0;
        while (i < getlstPO().size() && trouve == false) {
            if (getlstPO().get(i).getPomail().equals(mail)) {
                trouve = true;
                position = i;
            }
            i++;
        }

        return getlstPO().get(position);

    }
/**
 * get a structure of DAP from Database by its id
 * @param dsid
 * @return 
 */
    public Dapstructure getDS(int dsid) {
        boolean trouve = false;
        int i = 0;
        int position = 0;
        while (i < getLstDapStructure().size() && trouve == false) {
            if (getLstDapStructure().get(i).getDsname().equals(dsid)) {
                trouve = true;
                position = i;
            }
            i++;
        }
        return getLstDapStructure().get(position);

    }
/**
 * get all Step from Database
 * @return 
 */
    public List<Stepvalidation> getLststepdap() {
        return session.getNamedQuery("HQL_ALL_STEPDAPCOM").list();
    }
/**
 * get a step by it title
 * @param title
 * @return 
 */
    public Stepvalidation getStepbytitle(String title) {
        System.out.println("aaaaadsdsdsds" + getLstStepvalidation());
        boolean trouve = false;
        int i = 0;
        int position = 0;

        while (i < getLstStepvalidation().size() && trouve == false) {
            System.out.println("111titre" + getLstStepvalidation().get(i).getSvname());
            System.out.println("verifie titre" + getLstStepvalidation().get(i).getSvname().equals(title));
            if (getLstStepvalidation().get(i).getSvname().equals(title) && !(getLststepdap().contains(getLstStepvalidation().get(i)))) {

                trouve = true;
                position = i;
            }
            i++;
        }

        return getLstStepvalidation().get(position);

    }
/**
 * get a step by its id
 * @param svid
 * @return 
 */
    public Stepvalidation getStepbyid(int svid) {
        boolean trouve = false;
        int i = 0;
        int position = 0;
        while (i < getLstStepvalidation().size() && trouve == false) {
            if (getLstStepvalidation().get(i).getSvid().equals(svid)) {
                trouve = true;
                position = i;
            }
            i++;
        }

        return getLstStepvalidation().get(position);

    }
/**
 * insert into database a new department
 * @param dname
 * @param ddescription
 * @param director 
 */
    public void saveDepartment(String dname, String ddescription, Employee director) {
        Department newdepartment = new Department(dname, ddescription, director);
        Transaction tr = session.getTransaction();
        tr.begin();
        session.saveOrUpdate(newdepartment);
        tr.commit();
    }
    /**
     * insert into database new department
     * @param dpt 
     */

    public void saveDepartmentobjet(Department dpt) {
        Transaction tr = session.getTransaction();
        tr.begin();
        session.saveOrUpdate(dpt);
        tr.commit();
    }
/**
 * link a step to a DAP structure also its order and its step rollback 
 * @param dsid
 * @param svid
 * @param svidreturn
 * @param order 
 */
    public void addStepDap(int dsid, int svid, int svidreturn, int order) {
        DapcompositionId dapid;
        dapid = new DapcompositionId(dsid, svid, svidreturn);
        Dapcomposition dap;

        dap = new Dapcomposition(dapid, getStepbyid(svid), getStepbyid(svidreturn), getDS(dsid), order);
        Transaction tr = session.getTransaction();
        tr.begin();
        session.saveOrUpdate(dap);
        tr.commit();
    }
/**
 * get all DAP structure from Database
 * @return 
 */
    public List<Dapstructure> getLstDapStructure() {
        return session.getNamedQuery("HQL_ALL_DAPSTRUCTURE").list();
    }
/**
 * get all Step from Database
 * @return 
 */
    public List<Stepvalidation> getLstStepvalidation() {
        return session.getNamedQuery("lstStepValidation").list();
    }
/**
 * get a Department by its name
 * @param depname
 * @return 
 */
    
    public Department getdepepartment(String depname) {
        boolean trouve = false;
        int i = 0;
        int position = 0;
        System.out.println("lololo");
        System.out.println(getAllDepartment());
        while (trouve == false && i < getAllDepartment().size()) {
            System.out.println("dzdzdzdz");
            if (getAllDepartment().get(i).getDeptname().equals(depname)) {

                trouve = true;
                position = i;

            }

            i++;
        }
        return getAllDepartment().get(position);

    }
/**
 * get an employee by its id
 * @param empId
 * @return 
 */
    public Employee getEmployee(Integer empId) {
//         return (Employee) this.session.getNamedQuery("HQL_EMPLOYEE_ID").setParameter("id", empId).uniqueResult();
        return (Employee) this.session.load(Employee.class, empId);
    }
/**
 * get all Employees from Database
 * @return 
 */
    public List<Employee> getAllEmployee() {
        return this.session.getNamedQuery("HQL_ALL_EMPLOYEE").list();

    }
/**
 * set state of all DAP structures to False
 */
    public void setAllDapStructureCurrentFalse() {
        for (Dapstructure dapstructure : getLstDapStructure()) {
            dapstructure.setDscurrent(false);
        }
    }
/**
 * get All DAP version from Database
 * @return 
 */
    public List<Dapversion> getAllDapVersion() {
        return this.session.getNamedQuery("HQL_ALL_DAPVERSION").list();
    }
/**
 * get DAP structure by a Dap Version ID
 * @param dapv
 * @return 
 */
    public Dapstructure getDapstructure(int dapv) {
        int idDapstructure = (Integer) session.getNamedQuery("SQL_DAPSTRUCTURE_DAPVERSION").setParameter("id", dapv).uniqueResult();
        return (Dapstructure) session.getNamedQuery("HQL_DAPS_ID").setParameter("id", idDapstructure).uniqueResult();
    }
/**
 * Get a DAP structure by its ID
 * @param iddap
 * @return 
 */
    public Dapstructure getDAPstructureid(int iddap) {
        return (Dapstructure) session.getNamedQuery("HQL_DAPS_ID").setParameter("id", iddap).uniqueResult();

    }
/**
 * get list of Step and its order in a DAP structure 
 * @param daps
 * @return 
 */
    public HashMap<Integer, Stepvalidation> getDapStep(Dapstructure daps) {
        HashMap<Integer, Stepvalidation> mapStep = new HashMap<>();
        List<Dapcomposition> lstDapcomp = session.getNamedQuery("HQL_ALL_STEPS").setParameter("id", daps.getDsid()).list();
        for (Dapcomposition step : lstDapcomp) {
            if (!mapStep.containsValue(step.getStepvalidationBySvid())) {
                mapStep.put(step.getSteporder(), step.getStepvalidationBySvid());
            }
        }
        return mapStep;
    }
/**
 * get state of a step in a DAP version
 * @param step
 * @param dapv
 * @return 
 */
    public String getStatstep(Stepvalidation step, Dapversion dapv) {
        Query statquery = session.getNamedQuery("SQL_STATE").setParameter("idstep", step.getSvid());
        statquery.setParameter("iddapversion", dapv);
        String res = (String) statquery.uniqueResult();
        return res;
    }
/**
 * get DAP version by its ID
 * @param iddapv
 * @return 
 */
    public Dapversion getDapversion(int iddapv) {
        return (Dapversion) session.getNamedQuery("HQL_DAPVERSION_ID").setParameter("id", iddapv).uniqueResult();
    }
/**
 * set a DAP version state to final validation
 * @param indapv 
 */
    public void updateDapversion(int indapv) {
        Dapversion dapv = getDapversion(indapv);
        dapv.setDvfinalvalidation(true);
        Transaction tr = session.getTransaction();
        tr.begin();
        session.update(dapv);
        tr.commit();
    }
/**
 * get all DAP version from Database
 * @return 
 */
    public List<Dapversion> getAllDaps() {
        Query query = session.getNamedQuery("HQL_ALL_DAPVERSION");
        List result = query.list();
        return result;
    }
/**
 * get a DAP version by its id
 * @param dvid
 * @return 
 */
    public Dapversion getDapVersionByID(String dvid) {
        Dapversion res = null;

        for (Dapversion dapv : getAllDaps()) {
            if (dapv.getDvidvtitle().equals(dvid)) {
                res = dapv;
            }
        }
        return res;
    }
/**
 * get all decisions linked to a Dap version ID
 * @param dvid
 * @return 
 */
    public ArrayList<Decision> getAllDecbyDAP(String dvid) {
        Dapversion dapv = getDapVersionByID(dvid);
        ArrayList<Decision> res = new ArrayList<>();
        for (Decision deci : getAllDec()) {
            if (deci.getDapversion().equals(dapv)) {
                res.add(deci);
            }
        }

        return res;
    }
/**
 * get a Decision by its id
 * @param id
 * @return 
 */
    public Decision getDecisionById(Integer id) {
        return (Decision) session.getNamedQuery("HQL_ALL_DECISION_ID").setParameter("decisionid", id).uniqueResult();
    }
/**
 * get all document linked  to a decision
 * @param decision
 * @return 
 */
    public List<Docversion> getAllDocversionForDecision(Decision decision) {
        return session.getNamedQuery("HQL_DOCVERSION_DECISION").setParameter("vardecision", decision).list();
    }
/**
 * get all decision from Database
 * @return 
 */
    public List<Decision> getAllDec() {
        Query query = session.getNamedQuery("HQL_ALL_DECISION");
        List result = query.list();
        return result;
    }
/**
 * get all Dap version in final validation state
 * @return 
 */
    public List<Dapversion> getDapVersionvalidated() {
        return session.getNamedQuery("HQL_DAPVERSION_VALIDATED").list();
    }
/**
 * get a number of decision for a step in a dap structure
 * @param daps
 * @param step
 * @return 
 */
    public int getnbDesicionvalidate(Dapstructure daps, Stepvalidation step) {
        Query q = session.getNamedQuery("SQL_NBDECISION_V").setParameter("iddapstructure", daps.getDsid());
        q.setParameter("idstep", step.getSvid());
        return intValue(q.uniqueResult());
    }
/**
 * get a number of decision for a step in a dap structure
 * @param daps
 * @param step
 * @return 
 */
    public int getnbDesicioninvalidate(Dapstructure daps, Stepvalidation step) {
        Query q = session.getNamedQuery("SQL_NBDECISION_INV").setParameter("iddapstructure", daps.getDsid());
        q.setParameter("idstep", step.getSvid());
        return intValue(q.uniqueResult());
    }
/**
 * get percentage of decision validated
 * @param daps
 * @param step
 * @return 
 */
    public float pourcentagedecision(Dapstructure daps, Stepvalidation step) {
        if (!((getnbDesicionvalidate(daps, step) + getnbDesicioninvalidate(daps, step)) == 0)) {
            return ((getnbDesicionvalidate(daps, step))) * 100 / ((getnbDesicioninvalidate(daps, step) + getnbDesicionvalidate(daps, step)));
        } else {
            return 0F;
        }
    }


    /**
     * get costumer by its id
     * @param id
     * @return 
     */
    public Costumer getCostumerId(int id){
        return (Costumer)session.getNamedQuery("HQL_CUSTOMERS_ID").setParameter("id", id).uniqueResult();
    }
    /**
     * get all Costumer linked to a Dapstructure
     * @param iddaps
     * @return 
     */
    public List<Costumer> getCostumerDAPs(int iddaps){
        List<Costumer> lstres=new ArrayList<>();
        for(int i=0;i<session.getNamedQuery("SQL_COSTUMER_DAPS").setParameter("iddaps", iddaps).list().size();i++){
            lstres.add(getCostumerId((Integer)session.getNamedQuery("SQL_COSTUMER_DAPS").setParameter("iddaps", iddaps).list().get(i)));
        }
        return lstres;
    }
    /**
     * get number of decision validated by its Customer
     * @param cus
     * @param daps
     * @param step
     * @return 
     */
    
    public int getNbValidationsByCustomer(Costumer cus, Dapstructure daps, Stepvalidation step){
        Query q = session.getNamedQuery("SQL_NBDECISION_V_CUSTOMER").setParameter("iddapstructure", daps.getDsid());
        q.setParameter("idstep", step.getSvid());
        q.setParameter("cid", cus.getCid());
        return intValue(q.uniqueResult());
         }
/**
 * get number of decision invalidated by its Customer
 * @param cus
 * @param daps
 * @param step
 * @return 
 */
    public int getNbInvalidationsByCustomer(Costumer cus, Dapstructure daps, Stepvalidation step) {
        Query q = session.getNamedQuery("SQL_NBDECISION_INV_CUSTOMER").setParameter("iddapstructure", daps.getDsid());
        q.setParameter("idstep", step.getSvid());
        q.setParameter("cid", cus.getCid());
        return intValue(q.uniqueResult());
    }
    /**
     * get percentage of decision validated by its Customer
     * @param cus
     * @param daps
     * @param step
     * @return 
     */
    
    public float pourcentagedecisionCustomer(Costumer cus, Dapstructure daps, Stepvalidation step) {
        if (!((getNbValidationsByCustomer(cus, daps, step) + getNbInvalidationsByCustomer(cus,daps, step)) == 0)) {
            return ((getNbValidationsByCustomer(cus,daps, step))) * 100 / ((getNbInvalidationsByCustomer(cus,daps, step) + getNbValidationsByCustomer(cus,daps, step)));
        } else {
            return 0F;
        }
    }
    /**
     * get Customer by its name
     * @param name
     * @return 
     */
    public Costumer getCostumerByname(String name){
        return (Costumer)session.getNamedQuery("HQL_CUSTOMER_NAME").setParameter("name", name).uniqueResult();
    }
    public static void main(String[] args) {
        ProcessOwnerCore po = new ProcessOwnerCore();
//        System.out.println(po.getDapVersionvalidated().size());
        HashMap<Integer, Stepvalidation> hash;
//        hash = po.getDapStep(po.getDapstructure(59));

//        System.out.println("map" + hash);
//        System.out.println(po.getnbDesicioninvalidate(po.getDapstructure(58),po.getStepbyid(80)));
//        System.out.println(po.getnbDesicionvalidate(po.getDAPstructureid(58),po.getStepbyid(80)));
        System.out.println(po.pourcentagedecision(po.getDAPstructureid(139), po.getStepbyid(191)));
    }

}

//    public void setAllDapVersionCurrentTrue(Dapversion dap) {
//        
//        dap.setDvfinalvalidation(true);
//    }

